; dAMN Grafix!!! the Lord has gifted you with TEXTMODE!!! >>:}
; 
; are ye repentant?!
;
; (c:) 256 byte demo by Sassa
;      sassa@apiary.sumy.ua
;   _____
; @()(_)	[ well, i have nothing common with Apiary Inc 
; /\\  		[ that is located at http:\\www.apiary.com\ 8))
;		[ though i was pleased to see, that such a page exists ;))
;
; contribution to the '99 assembly competition
;
; Supposed Effect:
;  hey, man! can't you see, though slight, but still 3d???? >>:}
;  image transparency, superposition of colors in textmode. damn grafix.
;
; Supposed Responsibility:
;  none. :)
;
; Requirements:
;  - a)i8086 cpu or better (if force_8086)
;    b)i386 cpu or better (otherwise)
;  - generic EGA video card or better. with monitor, of course :))))
;  
;  - DOS 1.x or higher; not MD'98 
;      (under MustDie'98 startup register values are defined wrong (!) ;) way)
;
;  - do not drink neither strong beverage for 3 days :)))
;
;
; to see the effect you'd better run it from a pure DOS. under multitasking it
; may blink somehow distorted and spoil the effect. ;(
;
; Compile:
;  tasm damgrafx.asm
;  tlink -t damgrafx.obj
;

.model tiny
.code
.startup

;;;force_8086	equ	1	; if force_8086 mode is defined (no 386 instr)
				; my proggie grows by two bytes, 
				; still fitting 256 bytes limit ;P


color_1		equ	4		; colors of the film and screen image
color_2		equ	6		; ok, ok: i know, red and brown look
				; aggressive, but i had no space to pick
				; a better palette.
				; hint: do not use intensive colors. they yuck.

next_v_page	equ	1000h		; offset for the next video page

code2		equ	00000000b	; codes for EOT
code1		equ	01010101b

	call	off			; clrscr

        mov     bh,0b8h                 ; now BX=B800
        mov     es,bx

        scasw				; now DI=0 ;P (refer startup values)

        mov     si,offset img1

	mov	dx,color_1*100h+'@'	; set the color and filler char
l2:
        lodsb
	cmp	al,code1		; is it the EOT signal for the first
	jnz	l1_     		; table?

	add	di,next_v_page		; yes, right. let's fill the screen
	mov	dh,color_2		; image now.
	lodsb
l1_:
	mov	cl,al
	jcxz	off1			; oh, may be it is EOT for the next table?

	mov	ch,1			; nai, set stop bit for the bit map
loop1:
	mov	ax,dx
	shr	cx,1		; CX is not zero unless stop bit is shifted off
;;;	jz	l2			; sorry, ZF is not altered
					; on i186/188 processors after SHx
	jcxz	l2			; anyway, CX is zero ;)))
					; CX==0 -- the bit image is all passed
	jc	l21			; CY -- put filler

	mov	ah,0	      		; NC -- put blank 
					; ('put black' sounds better, though ;)
l21:
    	stosw
	jmp	short loop1		; shift next bit
off1:
;;
;; image is ready. rock-n-scroll! ;)
;;

        mov     dx,3d4h			; base video port

        mov     ax,0ch+next_v_page/2
        out     dx,ax		; setting start offset of the videopage
				; hi part; lo is still zero
				; now it should normally display the second
				; video page.
			;AH=(next_v_page/256)/2: take heed, that offset is taken
			; within zero color plane, thus twice less than
			; cpu sees it.

; we'll need:
; LCR: 3d4h, 18h
;   scan line for a split image: image from the actual video page is 
;     displayed above this line, and below it the image from the 0 offset
;     is displayed.
;
; OVR: 3d4h, 7 
;
; ...-+---4----+-...
;     | LCR D8 | 
;      ^^^^^^^ yeah, it is
;
; MSLR: 3d4h, 9 
; ...-+---6----+-...
;     | LCR D9 | 
; 
;


;
; film is the thing that slides behind (or is it on the top of?) the main image
;  there's some text written on it ;) now you can see?
;
;
; DI == Lowest possible scanline of the top of the film
;
; BX == Current point of the top of the film
;
;
	mov	bx,(25-5)*16		; 5 lines above the bottom of normal
        mov     di,bx			; VGA screen (well, on EGA the film may
			; disappear for some time due to this
			; should be set to (25-5)*14 then;
			; although i have no space to check
			; for the char height, it _works_)
wait_vert:

inc_1   label   byte
        dec     bx			; flip-flop; once it is inc, 
					; the other time it is dec ;))
        jz      slide_back		; ZF=1 if reached the top of the screen
					; flip the flop :))
        cmp     bx,di
        jc      n_sb			; CY - oh, well, obviously, if the 
slide_back:				;  utmost bottom line is reached
        xor     byte ptr inc_1,8                ; INC->DEC, DEC->INC

n_sb:

        mov     ah,8                    ; signal to wait vertical retrace
        mov     cx,di			; count for DI lines

wait_back:
        mov     dl,0dah
wait_:
        in      al,dx
        test    al,ah			; check the retrace flag
        jz      wait_

wait_1:
        in      al,dx
        test    al,ah
        jnz     wait_1
                        		; NC, so DAS will do ok.
        mov     ah,1				; now we'll wait for horiz

        in      al,60h
	das				; any released key...
				; well, actually, not _any_, but 
        js      off	; works for any key from ESC upto scancode of 'P'
			; this trick provides waiting for the key being released
	; also divert values for AH _are_ possible (can be nonzero) this time :P
	; (in lieu of DEC AX, as some coders do;
	; some shells hook 9, so released ESC is retrieved after 
	; proggie has done all its evil deeds. i mean, irq on key release can be 
	; signaled _after_ the program terminates (if the demo is as smart and 
	; quick as this one ;))))
			
        loop    wait_back               ; trace as much as CX scan lines

	push	bx

	neg	bp                      ; BP==undefined, but it _will_ do the 
					; trick ;)
        js      set_split

        mov     bx,-1
       					; so, BX==current_scanline one time
					; and BX==somewhere_out_of_the_screen 
					; the other time
set_split:                              ; obviously this will do the "film"
        mov     dl,0d4h			; transparent

        mov     ah,bl
        mov     al,18h                  ; 18h = LCR : Line Compare Register
        out     dx,ax

        mov     al,7                    ; OVR: there's 8-th bit for LCR
        out     dx,al

        inc     dx
        in      al,dx

ifdef	force_8086
        mov     cl,4		
        shl     bh,cl
else
	.386    		
	shl	bh,4
endif
        mov     ah,bh

        and     ah,00010000b
        and     al,11101111b            ; Set the 8-th bit for LCR
        or      al,ah
        out     dx,al
        dec     dx

        mov     al,9                    ; MSLR
        out     dx,al

        inc     dx
        in      al,dx

        shl     bh,1
        and     bh,01000000b
        and     al,10111111b            ; set the 9-th bit for LCR
        or      al,bh
        out     dx,al

        pop     bx

        jmp     short wait_vert		; wait for vertical retrace

off:
	mov	ax,3
	int	10h
_ret:
        ret

;
; .OOOOO..OOO..O...O.OOOOO.O...O..OOO..OOOO...OOO.....OO...OOO..O...O..OOO..OOOO.
; ...O...O...O..O.O....O...OO.OO.O...O.O...O.O...O...O.O..O...O.O...O.O...O.O...O
; ...O...OOOOO...O.....O...O.O.O.O...O.O...O.OOOOO..O..O..OOOOO.O...O.OOOOO.OOOO.
; ...O...O......O.O....O...O...O.O...O.O...O.O......OOOOO.O......O.O..O.....O..O.
; ...O....OOO..O...O...O...O...O..OOO..OOOO...OOO......O...OOO....O....OOO..O...O
;
img1    label	byte

	db      00111110b, 00100111b, 11111010b, 00100010b, 11100111b 
	db      01110001b, 00110000b, 01001110b, 11100100b, 00111100b 
	db      10001000b, 01001000b, 00100001b, 10110110b, 00101000b 
	db      10001010b, 00101000b, 01010001b, 00010100b, 01000101b 
	db      10001000b, 10001111b, 00100000b, 10101010b, 00101000b 
	db      11111010b, 00100100b, 01011111b, 11110100b, 00111101b 
	db      10001000b, 01000000b, 00100001b, 10100010b, 00101000b 
	db      00001010b, 01111100b, 10000001b, 00010010b, 00100100b 
	db      00001000b, 00100111b, 00100010b, 00100010b, 11100111b 
	db      01110001b, 00100000b, 00001110b, 11100001b, 01000100b 
	db	code1

;
; ..O...OOO....O.....OOO..OOOO...OOO....OOOO........OOOO...O....OOOO..OOOO...O...
; .O...O.....O..O...O...O.O.....O.......O...O......O......O.O..O.....O......O.O..
; .O...O........O......O..OOOO..OOOO....OOOO........OOO..O...O..OOO...OOO..O...O.
; .O...O.....O..O....OO.......O.O...O...O...O..........O.OOOOO.....O.....O.OOOOO.
; ..O...OOO....O....OOOOO.OOOO...OOO....OOOO.......OOOO..O...O.OOOO..OOOO..O...O.
;

	db      11000100b, 00100001b, 00111000b, 10001111b, 11000011b 
	db      00000011b, 01111000b, 10000100b, 11100111b, 00010001b 
	db      00100010b, 01001000b, 01000100b, 01000001b, 01000000b 
	db      00000100b, 00000100b, 01001010b, 00010000b, 00101000b 
	db      00100010b, 01000000b, 00100000b, 11001111b, 11000011b 
	db      00000011b, 00111000b, 10010001b, 11100011b, 01000100b 
	db      00100010b, 01001000b, 00011000b, 01010000b, 01000100b 
	db      00000100b, 01000000b, 00011111b, 00000100b, 01111101b 
	db      11000100b, 00100001b, 01111100b, 10001111b, 11000011b 
	db      00000011b, 00111100b, 11010001b, 11110011b, 01000100b 
	db	code2

        end

